home *** CD-ROM | disk | FTP | other *** search
-
- romable/romable romable/romable
-
- ROMABLE.DOC
-
- GENERATING ROMABLE FIRMWARE
-
- REFERENCES
-
- Please refer to the following DCC options:
-
- -pi generate position independant code. All code references
- forced to PC-relative
-
- -pr generate residentable position independant code. Unless
- -mw is specified A4 relative addressing is used for data
- items. All code references forced to PC-relative.
-
- -ma specify that initialized data + bss will be hardwired to
- a known address
-
- -mw specify that initialized data + bss will be hardwired to
- a known address and all of data + bss occurs somewhere
- within the first 32KBytes of the address space
- (0x0000-0x7FFF). Also allows DICE to use A4 as a register
- variable.
-
- -ms const items go into EPROM in local cases
-
- -mS const items go into EPROM in local and external cases
-
- The following documentation may appear confusing, but only because so
- many possibilities exist when one intends to put code in ROM. When you
- are in doubt, it is usually a good idea to write a small test source
- file, compile it, link it with symbols, and then look at the resulting
- executable with DOBJ.
-
-
- MAKING ROMABLE PROGRAMS
-
- DICE has the capability to generate ROMABLE programs. That is, program
- binaries that you can use to directly burn an EPROM. When generating
- ROMABLE code you have more data model options available to you. The
- basic idea of ROMd code is as follows:
- ________________
- FIXED ADDRESS = EPROM | |
- | 68000 vectors | const data objects
- |----------------|
- | CODE |
- |----------------|
- | const DATA | string constants and other
- | | const items, stays in eprom.
- |----------------|
- | read-only copy |
- | of initialized | this is copied to a working
- | data | RAM copy by the reset code
- |________________|
-
- ________________
- FIXED ADDRESS = RAM | run-time copy | (copied from EPROM by startup)
- | of initialized |
- | data |
- |----------------| (cleared by EPROM startup)
- | run-time BSS |
- |________________|
-
-
- From the above you have two basic choices in terms of where your
- RUN-TIME DATA is based. If your RAM exists in low-memory
- (0x0000-0x7FFF) you may choose to compile your code to use the
- ABSOLUTE-WORD addressing mode. This modes takes the same space as the
- A4-RELATIVE addressing mode yet does not require use of the A4 register
- and, in fact, the A4 register will then be available for use as a
- register variable.
-
- If you have minimal RAM in low-memory or your DATA+BSS is larger than
- 32KBytes (yes, that's 32KBytes people, not 64KBytes), then you will
- have to choose either the formal large-data model or the A4-relative
- small data model. If you initialized data is over 64KBytes you can
- still use the small-data model for most objects by using the __far
- keyword judiciously.
-
- NOTE: in all cases you can allocate or generate points for any ram
- location, this just refers to accesses of declared variables! Pointers
- are always 32 bits.
-
- model options advantages disadvantages
-
- absolute-word -mw -ms no need for A4 low 32KBytes only
- A4 available as
- reg variable
-
- small-data -ma -ms RAM can be anywhere requires A4
- must use __geta4
-
- large-data -ma -mD -ms RAM can be anywhere code is larger
- libs must all be
- large-data
-
-
- CODE MODEL
-
- The CODE MODEL is normally left at PC-relative and should not present a
- problem.
-
- CONST DATA
-
- You want to use the -ms option or even the -mS option (see DCC.DOC for
- the differences). This will place all string constants in EPROM and
- IN THE CODE SEGMENT, thus this initialized data will NOT take up space
- in RAM. Any 'const' initialized data will be placed in the code segment
- and thus in EPROM. Any non-const initialized data will be copied from
- EPROM into RAM by your reset-startup code.
-
- Any tables that you declare that you will never modify should be
- declared const so they reside in EPROM and do not take up space in RAM.
- On the otherhand, if your EPROM is running 6 wait states and your RAM
- is running 0 you might consider not using 'const'.... assuming you have
- a lot of RAM.
-
- When your code is less than 32KBytes big you can use -pi or -pr and
- should definitely use -mS. When your code is larger than 32KBytes you
- cannot use -mS unless you are absolutely positive pc-relative const
- data references do not exceed the word-relative range.
-
- RESET VECTOR, DATA MODEL SETUP
-
- If your EPROM is mapped into low memory on boot you can declare a vector
- table by declaring a CONST LONG array as the first data object in the
- first object module that you link to create the executable:
-
- const long ROMVectorTable[] = {
- InitialSSP,
- ResetVector,
- .
- .
- .
- };
-
- Remember, this must be the first data declaration in the first object
- module!!! If you are using the A4-RELATIVE small-data model you must
- qualify your ResetVector with the __geta4 type qualifier to set up A4.
-
- In most cases you will want ResetVector to point to some assembly which
- initializes your RAM DATA & BSS before calling C code. The assembly
- normally looks like this (this would be the second object in the link):
-
- ; RESET exception, copy initialized data to RAM and clear
- ; BSS area before calling rom_main()
- ;
- ; Assumes less than 256KBytes of data and 256KBytes of BSS
-
- xref __DATA_BAS ; linker generated symbols
- xref __ABSOLUTE_BAS
- xref __DATA_LEN
- xref __BSS_LEN
- xref _rom_main
-
- _ResetVector
- lea __DATA_BAS,A0 ; ROM data
- lea __ABSOLUTE_BAS,A1 ; RAM data
- move.w #__DATA_LEN,D0 ; long words of data
- bra trentry
- trloop move.l (A0)+,(A1)+ ; copy EPROM copy to run-time
- trentry dbf D0,trloop ; RAM copy.
-
- move.w #__BSS_LEN,D0 ; long words of BSS (follows data)
- moveq.l #0,D1
- bra trbentry
- trbloop move.l D1,(A1)+ ; clear run-time RAM
- trbentry dbf D0,trbloop
-
- jmp _rom_main(pc)
-
- Where rom_main() is your C main routine qualified with __geta4 (if you
- are using the A4-RELATIVE data model). Any special items, such as
- the EPROM getting mapped at reset, must be dealt with as well, usually
- before the reset code sets up the run-time enviroment.
-
- If you are using the ABSOLUTE-WORD data model DO NOT USE __GETA4!
- Specifically, the -mw option TELLS DICE THAT A4 IS FREE FOR USE AS A
- NORMAL REGISTER VARIABLE. This gives you an extra register variable if
- you haven't guessed!
-
- EXAMPLE PROGRAM
-
- Assume the above assembly module has been assembled and is called
- 'romc.o'. The following C program is called 'test.c'. In all cases
- the code may start anywhere.
-
- Also, in all cases note that ROMC.O is specified AFTER test in the
- DCC line (that also serves as the link line). This is because for
- a standalone product we want our CONST data object that is the
- ROM VECTOR TABLE to be first. Of course, if you put the ROM VECTOR
- TABLE in ROMC.A instead of TEST.C then ROMC.A would go first. To
- put the ROM VECTOR TABLE in ROMC.A it should be the first data
- object declarations (dc.l's) in the CODE segment.
-
-
- (1) SMALL-DATA-MODEL
-
- extern void TrapReset();
- extern char SSp[512];
-
- const long RomVectors[] = { (long)SSp, (long)TrapReset };
-
- char SSp[512]; /* our supervisor stack in BSS */
-
- __geta4 void
- rom_main()
- {
- short i;
-
- for (;;) {
- for (i = 0; i < 10000; ++i) {
- <do something here with i>
- }
- }
- }
- note, ram can be beyond 64K
- v
-
- COMPILE: dcc test.c romc.o -ma 0x10000 -o t:test -r -v -lrom
- romable t:test -o t:test.bin -D 0x10000 -C 0x0
- burn eprom using test.bin
-
-
- (2) ABSOLUTE WORD DATA MODEL
-
- The source code is the same except you do not need __geta4. Here
- I am assuming RAM starts at, say, 0x2000.
-
- void
- rom_main()
- {
- ...
- }
-
- COMPILE: dcc test.c romc.o -mw 0x2000 -o t:test -r -lrom
- romable t:test -o t:test.bin -D 0x2000 -C 0x0
- burn eprom using test.bin
-
- (3) ABSOLUTE LONG DATA MODEL
-
- The source code is the same as for (2). Here the RAM may start
- anywhere (also true in (1)).
-
- COMPILE: dcc test.c romc.o -ma 0x10080 -o t:test -r -lrom
- romable t:test -o t:test.bin -D 0x10080 -C 0
- burn eprom using test.bin
-
- (4) EXAMPLE OF EPROM INITIALLY MAPPED AT 0x0000 BUT REMAPPABLE TO
- SOMEWHERE ELSE
-
- In this case the assembly, ROMC.A, must relocate the EPROM back
- to where it should be before initializing the data segment. Here
- your initial CONST data is the EPROM VECTOR TABLE, and your initial
- non-CONST INITIALIZED data (because BSS gets stuck after all
- initialized data) will be your RAM VECTOR TABLE.
-
- In this example I assume that RAM will be mapped into 0x0000-
- by the time rom_main() gets called. Compilation depends on the
- data model. The example below uses the ABSOLUTE WORD data model.
-
- extern void TrapReset();
- extern char SSp[512];
-
- const long RomVectors[] = { (long)SSp, (long)TrapReset };
- long RamVectors[] = { (long)SSp, (long)TrapReset, ... };
-
- char SSp[512]; /* our supervisor stack in BSS */
-
- void
- rom_main()
- {
- ...
- }
-
- In this compilation example I am assuming the RAM will be at 0x0000 and
- the ROM, say, at 0x20000 (above the 64KBmark)
-
- COMPILE: dcc test.c romc.o -mw 0 -o t:test -r -lrom
- romable t:test -o t:test.bin -D 0 -C 0x20000
- burn eprom using test.bin
-
- USING ROM.LIB
-
- ROM.LIB is generated from LIB/FILES.ROM3LIB and contains those modules
- from C.LIB that do not declare any variables and are position
- independant. Modules in the library are entirely position independant.
- If you use library calls instead of macros in <ctype.h> for ctype
- functions those are position independant as well ... they use
- pc-relative to access the lookup tables (which are declared const).
-
- Nothing in ROM.LIB declares any data variables. The idea is to link
- your code with ROM.LIB instead of C.LIB to ensure that incompatible
- routines are never included by mistake.
-
- Warning: If you want position independant code you must compile with
- -pi or -mS, especially when accessing <ctype.h> macros. Accessing
- <ctype.h> macros and not using either the above options will result in
- absolute-code references to ctype's lookup tables.
-
- ------------------------------------------------------------------------
- MAKING RAM MODULES
-
- Generating a binary image for an executable that is meant to run from
- RAM instead EPROM is relatively easy. In many cases you want only a
- single copy of the data (instead of two copies as in EPROM modules..
- the permanent initialized data in EPROM and the run-time data+bss in
- RAM). This means that the program is not-reentrant... once an
- initialized data variable is modified it stays modified. If this is
- not desireable you can use the same methods as were described for
- making EPROM code combined with methods (see LIB/AMIGA/C_PR.A) to
- allocate the data space run-time.
-
- If you want to generate resident style modules use the small-data model
- version in the previous section 'MAKING ROMABLE PROGRAMS' and simply
- apply the concept of downloading such a module into RAM instead of ROM.
- It is especially easy when the code is completely position independant
- because your firmware does not have to deal with relocation at all.
-
- This section describes standalone modules with UNsharable code because
- the code is completely position independant and references only one set
- of data.
-
- ________________
- ANY ADDRESS IN RAM |startup |
- | CODE |
- |----------------|
- | initialized |
- | data |
- |----------------|
- | |
- | BSS |
- |----------------|
-
- The code uses a single PC-relative reference to find the start of the
- data, then generates the A4 register to point to the data section.
- NOT A SINGLE 32-BIT REFERENCE EXISTS.
-
- WARNING: The module has only one set of data. Once initialized data
- is modified it stays modified through multiple invocations of the module
-
- The advantage of using a position independant module is obvious... you
- can copy it to any point in ram as-is and then call it! For small
- 68000 boxes with limited memory this is definite plus as it greatly
- simplifies the loading mechanism.
-
- To create a 100% relocatable module, the code must be less than 32K
- and the data less than 64K. You must use the -pi option when compiling
- all source modules, when running dlink, and when running ROMABLE.
-
- The -pi option, amoung other things, puts the __ABSOLUTE_BAS and
- __DATA_BAS linker symbols in the code section. Actually, dlink puts
- the entire program into a single CODE hunk!
-
- dcc -c test.c -pi
- dlink -pi rampi.o test.o -lrom -o test
- romable test -o test.bin -pi
-
- RAMPI.A is something you have to write, but you do have a template.
- Take a look at LIB/AMIGA/C_PI.A as an example (also note that
- LIB/AMIGA/X.A is also required). Remember that the autoinit sections
- must be entirely supported though not necessarily the autoexit sections,
- it depends on your application.
-
- USING ROM.LIB
-
- ROM.LIB is generates from LIB/FILES.ROM3LIB and contains compiler
- support routines that do not require any RAM. Modules in the library
- are entirely position independant. If you use library calls instead
- of macros in <ctype.h> for ctype functions those are position
- independant as well ... they use pc-relative to access the lookup
- tables (which are declared const).
-
- Nothing in ROM.LIB declares any data variables. The idea is to link
- your code with ROM.LIB instead of C.LIB to ensure that incompatible
- routines are never included (instead you get an undefined symbol error
- from the linker when you make a mistake).
-
- Warning: If you want position independant code you must compile with
- -pi or -mS, especially when accessing <ctype.h> macros.
-
-
-
- ------------------------------------------------------------------------
-
- ROMABLE exeFile -o outFile [-o outFile2] -C addr -D addr -pi
-
- addr: decimal, 0octal, or 0xHEX
-
- Romable generates a binary image for an executable compiled under DICE
- and is normally used to generate a ROMABLE raw binary output file.
-
- exeFile input executable linked with dlink
-
- -o outFile output binary (unformatted -- raw). If TWO -o options
- are specified the two output files will have even bytes
- and odd bytes respectively, which is what you need when
- you must program two eproms (one on the LSB data lines
- and one on the MSB data lines)
-
- example: -o out1 result: 01 02 03 04
-
- example: -o out1 -o out2 result (out1): 01 03
- result (out2): 02 04
-
-
- -C addr code start address, 0octal, decimal, or 0xHEX
-
- -D addr data start address, 0octal, decimal, or 0xHEX
-
- -DC place actual data+bss just after code (i.e. the
- result is intended to be downloaded into RAM, there
- is no duplicate data in this case).
-
- '-D addr' is not specified in this case
-
- -pi generate a position independant module. Neither
- -C or -D are specified in this case, and ROMABLE
- will warn you have any absolute references.
-
- Note that your custom startup code determines how much of __autoinit
- and __autoexit is to be supported. Note especially that __autoinit0
- MUST BE SUPPORTED because DICE will generate __autoinit0 sections to
- handle 32 bit data relocations run-time.
-
- ROMABLE generates a raw output file or files with the EPROM code first,
- and initialized data after the main code (still in EPROM) which, as
- has already been described, will be copied to RAM on reset by your
- startup routine.
-
- This startup-copying of initialized data and clearing of BSS makes it
- extremely easy to use DICE to generate ROMED applications without
- having to deal with major porting considerations.
-
-